#version 430

uniform mat4 u_view;
uniform mat4 u_proj;
uniform mat4 u_model;

uniform mat4 u_reflectview;
uniform mat4 u_reflectproj;

uniform sampler2D u_heightmap;
uniform sampler2D u_normal;
uniform sampler2D u_dudv;
uniform sampler2D u_reflection;
uniform sampler2D u_refraction;
uniform float u_scale; //for dem
uniform float u_offset;//for dem
uniform vec3 u_gnd2sun;//normalized.
uniform vec3 u_eyepos;// .
uniform float u_tick;

in vec2 vary_uvheight;
in vec2 vary_uvnormal;
in float vary_waterheight;
in vec3 vary_px2eye;
in vec4 vary_worldposi;

out vec4 fragColor;
float waterStrength = 0.01;
void main()
{
    float terrainHeight = (texture(u_heightmap, vary_uvheight).r + u_offset) * u_scale;
    if (vary_waterheight < terrainHeight) discard;

    vec2 dudv = (texture(u_dudv, vary_uvheight + u_tick).rg * 2.0 - 1.0) * waterStrength  ;

    vec2 normal_uv = vary_uvnormal  ;
    
    float normalRepeat = 16.0;//this value bigger, then the sparkles smaller and denser.
    vec3 nor0 = texture(u_normal, normal_uv * normalRepeat + dudv).rgb;
    vec3 nor = nor0.rbg;
    nor.x = nor.x * 2.0 - 1.0;
    nor.y *=1.0 ; //After many tries, this should not change!
    nor.z = nor.z * 2.0 - 1.0;
    nor = normalize(nor);
    float diff = dot(nor, u_gnd2sun);

    vec3 refldir = reflect(- u_gnd2sun, nor);
    vec3 viewdir = normalize(vary_px2eye);
    vec3 halfway = normalize(viewdir + u_gnd2sun);
    float spec = pow(max(dot(refldir, viewdir), 0.0), 32.0);
    float ambient = 0.0;
    vec3 watercolor = vec3(0.28, 0.40, 0.28);
    watercolor = watercolor * diff;//  + vec3(1.0)*spec ;

    //specular
    vec4 specolor = vec4(vec3(1.0) * spec *0.6, 1.0);

    //reflection
    vec4 reflection_ndc = u_reflectproj * u_reflectview * vary_worldposi;
    vec2 reflection_uv = vec2(reflection_ndc.x / reflection_ndc.w, reflection_ndc.y / reflection_ndc.w);
    reflection_uv = (reflection_uv + 1.0) * 0.5 + dudv;
    //prevent edge exception by OpenGL Water Tutorial 5: DuDv Maps ThinMatrix at 7:36
    reflection_uv = clamp(reflection_uv, 0.001, 0.999);
    vec4 reflection_color = texture(u_reflection, reflection_uv);

    //refraction
    vec4 refract_ndc = u_proj * u_view * vary_worldposi;
    vec2 refract_uv = vec2(refract_ndc.x / refract_ndc.w, refract_ndc.y / refract_ndc.w);
    refract_uv = (refract_uv + 1.0) * 0.5 + dudv;
    //prevent edge exception by OpenGL Water Tutorial 5: DuDv Maps ThinMatrix at 7:36
    refract_uv = clamp(refract_uv, 0.001, 0.999);
    vec4 refract_color = texture(u_refraction, refract_uv);

    //fresnel
    float fresnel = dot(viewdir, vec3(0.0, 1.0, 0.0));
    fresnel = pow(fresnel, 5.0);

    //fragColor = vec4(texture(u_normal, vary_uvnormal).rgb , 1.0);
    fragColor = vec4( mix( reflection_color.rgb, refract_color.rgb, fresnel ) + specolor.rgb,1.0) ;



}